/**
 * Copyright millionhere
 * Licensed under the Apache License, Version 2.0 (the "License");
 * You may see it at...
 *      http://www.apache.org/licenses/LICENSE-2.0
 */

package info.millionhere.keepsilent;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.ToggleButton;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;

public class MainActivity extends Activity implements OnClickListener, OnItemClickListener, OnItemLongClickListener{
    
    static final int TAG_REQUESTCODE_ADD = 1;
    static final int TAG_REQUESTCODE_EDIT = 2;
    
    private ToggleButton mButtonAvailable;
    private Button mButtonAdd;
    private Button mButtonSave;
    private Button mButtonAbort;

    private ListView mBlackListView;
    private BlackListViewAdapter mBlackListViewAdapter;
    
    public ArrayList<BlackListElement> BlackList_Array;
    public HashMap<String, BlackListElement> BlackList_Map;
    
    private static boolean bChanged;
    
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.main);

	mButtonAvailable = (ToggleButton)findViewById(R.id.button_available);
	mButtonAdd = (Button)findViewById(R.id.button_add);
	mButtonSave = (Button)findViewById(R.id.button_save);
	mButtonAbort = (Button)findViewById(R.id.button_abort);
	mBlackListView = (ListView)findViewById(R.id.list_blacklist);

	readBlackList();

	mBlackListViewAdapter = new BlackListViewAdapter(this, BlackList_Array);
	mBlackListView.setAdapter(mBlackListViewAdapter);

	mBlackListView.setItemsCanFocus(true);
	mBlackListView.setOnItemClickListener(this);
	mBlackListView.setOnItemLongClickListener(this);

	mButtonAvailable.setOnClickListener(this);
	mButtonAdd.setOnClickListener(this);
	mButtonSave.setOnClickListener(this);
	mButtonAbort.setOnClickListener(this);

	mButtonAvailable.setChecked(getServiceStatus());
	bChanged = false;
    }
    
    @Override
    protected void onDestroy(){

	super.onDestroy();
    }
    
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event){
	if (keyCode == KeyEvent.KEYCODE_BACK){
	    if (bChanged)
		return confirmQuit();
	    else
		finish();
	}
	return false;
    }
    
    private boolean confirmQuit(){
	new AlertDialog.Builder(MainActivity.this).
	setTitle(getString(R.string.text_confirm_title)).
	setMessage(getString(R.string.text_confirmquit_message)).
	setPositiveButton(getString(R.string.text_confirm_positive), new DialogInterface.OnClickListener(){public void onClick(DialogInterface arg0, int arg1){finish();}}).
	setNegativeButton(getString(R.string.text_confirm_negative), null).
	show();
	return false;
    }
    private void readBlackList(){
	BlackListXmlAdaptor BlackListXml = new BlackListXmlAdaptor();
	BlackList_Map = BlackListXml.Read();
	BlackList_Array = new ArrayList<BlackListElement>(BlackList_Map.values());
	
	sortBlackListByAddress(BlackList_Array);
    }
    
    @SuppressWarnings("unchecked")
    private void sortBlackListByAddress(ArrayList<BlackListElement> blackList){
	Collections.sort(blackList, new Comparator(){
	    public int compare(Object o1,Object o2) {
		return ((BlackListElement)o1).sAddress.compareTo(((BlackListElement)o2).sAddress);
	    }
	});
    }
    
    public void onClick(View v) {
        switch(v.getId()){
            case R.id.button_available:
        	ButtonAvailableClicked();
                break;
            case R.id.button_add:
        	ButtonAddClicked();
        	break;
            case R.id.button_save:
        	ButtonSaveClicked();
        	break;
            case R.id.button_abort:
        	ButtonAbortClicked();
        	break;
            default:
        	break;
        }
    }
    
    public void onItemClick(AdapterView<?> av, View v, int position, long arg3){
	if (v.getId() == R.id.list_item_with_checkbox){
	    showAddActivity(BlackList_Array.get(position), position);
	}
    }
    
    public boolean onItemLongClick(AdapterView<?> av, View v, final int position, long arg3){
	if (v.getId() == R.id.list_item_with_checkbox){
	    new AlertDialog.Builder(MainActivity.this).
	    setTitle(getString(R.string.text_confirm_title).toString()).
	    setMessage(getString(R.string.text_confirmdelete_message).toString()).
	    setPositiveButton(getString(R.string.text_confirm_positive).toString(), new DialogInterface.OnClickListener(){public void onClick(DialogInterface arg0, int arg1){deleteRule(position);}}).
	    setNegativeButton(getString(R.string.text_confirm_negative).toString(), null).
	    show();
	}
	return true;
    }
    
    public void ButtonAvailableClicked(){

	if (!mButtonAvailable.isChecked()){
	    this.stopService(new Intent(this, KeepSilentService.class));
	}
	else{
	    this.startService(new Intent(this, KeepSilentService.class));
	}
	
	boolean serviceStatus = getServiceStatus();
	ConfigXmlAdaptor configXmlAdaptor = new ConfigXmlAdaptor();
	configXmlAdaptor.SetServiceOnBoot(serviceStatus);
	
	mButtonAvailable.setChecked(serviceStatus);
    }
    
    public void ButtonAddClicked(){
	showAddActivity();
    }
    
    public void ButtonSaveClicked(){
	BlackListXmlAdaptor BlackListXml = new BlackListXmlAdaptor();
	BlackListXml.Write(BlackList_Array);
	if (getServiceStatus())
	    this.startService(new Intent(this, KeepSilentService.class));
	this.finish();
    }
    
    public void ButtonAbortClicked(){
	this.finish();
    }
    
    private void showAddActivity(){
	startActivityForResult(new Intent(this, AddNewRuleActivity.class), TAG_REQUESTCODE_ADD);
    }
    private void showAddActivity(BlackListElement rule, int position){
	Intent intent = new Intent();
	intent.setClass(this, AddNewRuleActivity.class);
	Bundle bundle = new Bundle();
	bundle.putString(AddNewRuleActivity.TAG_ADDRESS, rule.sAddress);
	bundle.putString(AddNewRuleActivity.TAG_COMMENT, rule.sComment);
	bundle.putInt(AddNewRuleActivity.TAG_POSITION, position);
	intent.putExtras(bundle);
	startActivityForResult(intent, TAG_REQUESTCODE_EDIT);
    }
    
    @Override 
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) { 
	Bundle bundle;
	switch (requestCode){
	case TAG_REQUESTCODE_ADD:
	    if (resultCode == RESULT_OK)
	    {
		bundle = intent.getExtras();
		addRule(bundle.getString(AddNewRuleActivity.TAG_ADDRESS), bundle.getString(AddNewRuleActivity.TAG_COMMENT), true);
	    }
	    break;
	case TAG_REQUESTCODE_EDIT:
	    if (resultCode == RESULT_OK)
	    {
		bundle = intent.getExtras();
		deleteRule(bundle.getInt(AddNewRuleActivity.TAG_POSITION));
		addRule(bundle.getString(AddNewRuleActivity.TAG_ADDRESS), bundle.getString(AddNewRuleActivity.TAG_COMMENT), true);
	    }
	    break;
	default:
	    break;
	}
    }
    
    private void addRule(BlackListElement rule){
	// remove duplicate item
	for (Iterator<BlackListElement> iter = BlackList_Array.iterator();iter.hasNext();){
	    if (iter.next().sAddress.equals(rule.sAddress)){
		iter.remove();
	    }
	}
	BlackList_Array.add(rule);
	sortBlackListByAddress(BlackList_Array);
	mBlackListViewAdapter.notifyDataSetChanged();
	bChanged = true;
    }
    
    private void deleteRule(int position){
	BlackList_Array.remove(position);
	sortBlackListByAddress(BlackList_Array);
	mBlackListViewAdapter.notifyDataSetChanged();
	bChanged = true;
    }
    
    private void addRule(String address, String comment, boolean available){
	BlackListElement rule = new BlackListElement(address, comment, available);
	addRule(rule);
    }
    
    private boolean getServiceStatus(){
	ActivityManager mActivityManager = (ActivityManager)getSystemService(ACTIVITY_SERVICE);
	List<ActivityManager.RunningServiceInfo> runningServicesList = mActivityManager.getRunningServices(30);
	for(ActivityManager.RunningServiceInfo t:runningServicesList){
            if(KeepSilentService.class.toString().contains(t.service.getClassName())){
                return true;
            }
        }
	return false;
    }
    
    private static class BlackListViewAdapter extends BaseAdapter {
	private LayoutInflater mInflater;
	private ArrayList<BlackListElement> mBlackList_Array;
	
	public BlackListViewAdapter(Context context, ArrayList<BlackListElement> BlackList_Array){
	    mBlackList_Array = BlackList_Array;
	    mInflater = LayoutInflater.from(context);
	}

	public int getCount() {
	    return mBlackList_Array.size();
	}

	public BlackListElement getItem(int position) {
	    return mBlackList_Array.get(position);
	}

	public long getItemId(int position) {
	    return position;
	}

	public View getView(final int position, View convertView, ViewGroup parent) {
	    ViewHolder holder;
	    
	    if (convertView == null) {
                convertView = mInflater.inflate(R.layout.list_item_with_checkbox, null);
                holder = new ViewHolder();
                holder.address = (TextView)convertView.findViewById(R.id.text_address);
                holder.comment = (TextView)convertView.findViewById(R.id.text_comment);
                holder.available = (CheckBox)convertView.findViewById(R.id.checkbox_in_list);
                convertView.setTag(holder);
	    } else {
                holder = (ViewHolder)convertView.getTag();
            }
	    
	    holder.address.setText(mBlackList_Array.get(position).sAddress);
	    holder.comment.setText(mBlackList_Array.get(position).sComment);
	    holder.available.setChecked(mBlackList_Array.get(position).bAvailable);
	    
	    //Set CheckBox click listener
	    holder.available.setOnClickListener(new OnClickListener() {
		public void onClick(View view) {
		    BlackListElement rule = mBlackList_Array.get(position);
		    rule.bAvailable = !rule.bAvailable;
		    mBlackList_Array.set(position, rule);
		    bChanged = true;
		}
	    });

	    return convertView;
	}
	    
	static class ViewHolder {
            TextView address;
            TextView comment;
            CheckBox available;
        }
    }
}